home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1998 November / Freeware November 1998.img / dist / fw_KLJxearth.idb / usr / freeware / src / xearth-1.0 / render.c.z / render.c
C/C++ Source or Header  |  1997-09-09  |  14KB  |  640 lines

  1. /*
  2.  * render.c
  3.  * kirk johnson
  4.  * october 1993
  5.  *
  6.  * RCS $Id: render.c,v 1.1 1995/11/21 18:59:19 swinokur Exp $
  7.  *
  8.  * Copyright (C) 1989, 1990, 1993, 1994, 1995 Kirk Lauritz Johnson
  9.  *
  10.  * Parts of the source code (as marked) are:
  11.  *   Copyright (C) 1989, 1990, 1991 by Jim Frost
  12.  *   Copyright (C) 1992 by Jamie Zawinski <jwz@lucid.com>
  13.  *
  14.  * Permission to use, copy, modify and freely distribute xearth for
  15.  * non-commercial and not-for-profit purposes is hereby granted
  16.  * without fee, provided that both the above copyright notice and this
  17.  * permission notice appear in all copies and in supporting
  18.  * documentation.
  19.  *
  20.  * Unisys Corporation holds worldwide patent rights on the Lempel Zev
  21.  * Welch (LZW) compression technique employed in the CompuServe GIF
  22.  * image file format as well as in other formats. Unisys has made it
  23.  * clear, however, that it does not require licensing or fees to be
  24.  * paid for freely distributed, non-commercial applications (such as
  25.  * xearth) that employ LZW/GIF technology. Those wishing further
  26.  * information about licensing the LZW patent should contact Unisys
  27.  * directly at (lzw_info@unisys.com) or by writing to
  28.  *
  29.  *   Unisys Corporation
  30.  *   Welch Licensing Department
  31.  *   M/S-C1SW19
  32.  *   P.O. Box 500
  33.  *   Blue Bell, PA 19424
  34.  *
  35.  * The author makes no representations about the suitability of this
  36.  * software for any purpose. It is provided "as is" without express or
  37.  * implied warranty.
  38.  *
  39.  * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  40.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
  41.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT
  42.  * OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  43.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
  44.  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  45.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  46.  */
  47.  
  48. #include "xearth.h"
  49. #include "kljcpyrt.h"
  50.  
  51. static void new_stars _P((double));
  52. static void new_grid _P((int, int));
  53. static void new_grid_dot _P((double *, double *));
  54. static int dot_comp _P((const void *, const void *));
  55. static void render_rows_setup _P((void));
  56. static void render_next_row _P((s8or32 *, int));
  57. static void no_shade_row _P((s8or32 *, u_char *));
  58. static void compute_sun_vector _P((double *));
  59. static void orth_compute_inv_x _P((double *));
  60. static void orth_shade_row _P((int, s8or32 *, double *, double *, u_char *));
  61. static void merc_shade_row _P((int, s8or32 *, double *, u_char *));
  62.  
  63. static int      scanbitcnt;
  64. static ScanBit *scanbit;
  65. static s8or32   scan_to_pix[256];
  66.  
  67. static int    night_val;
  68. static int    day_val_base;
  69. static double day_val_delta;
  70.  
  71. static ExtArr   dots = NULL;
  72. static int      dotcnt;
  73. static ScanDot *dot;
  74.  
  75.  
  76. static int dot_comp(a, b)
  77.      const void *a;
  78.      const void *b;
  79. {
  80.   return (((const ScanDot *) a)->y - ((const ScanDot *) b)->y);
  81. }
  82.  
  83.  
  84. static void render_rows_setup()
  85. {
  86.   int i;
  87.  
  88.   scanbitcnt = scanbits->count;
  89.   scanbit    = (ScanBit *) scanbits->body;
  90.   dotcnt     = dots->count;
  91.   dot        = (ScanDot *) dots->body;
  92.  
  93.   /* precompute table for translating between
  94.    * scan buffer values and pixel types
  95.    */
  96.   for (i=0; i<256; i++)
  97.     if (i == 0)
  98.       scan_to_pix[i] = PixTypeSpace;
  99.     else if (i > 64)
  100.       scan_to_pix[i] = PixTypeLand;
  101.     else
  102.       scan_to_pix[i] = PixTypeWater;
  103. }
  104.  
  105.  
  106. static void render_next_row(buf, idx)
  107.      s8or32 *buf;
  108.      int     idx;
  109. {
  110.   int      i, i_lim;
  111.   int      tmp;
  112.   int      _scanbitcnt;
  113.   ScanBit *_scanbit;
  114.  
  115.   xearth_bzero((char *) buf, (unsigned) (sizeof(s8or32) * wdth));
  116.  
  117.   /* explicitly copy scanbitcnt and scanbit to local variables
  118.    * to help compilers figure out that they can be registered
  119.    */
  120.   _scanbitcnt = scanbitcnt;
  121.   _scanbit    = scanbit;
  122.  
  123.   while ((_scanbitcnt > 0) && (_scanbit->y == idx))
  124.   {
  125.     /* use i_lim to encourage compilers to register loop limit
  126.      */
  127.     i_lim = _scanbit->hi_x;
  128.     tmp   = _scanbit->val;
  129.     for (i=_scanbit->lo_x; i<=i_lim; i++)
  130.       buf[i] += tmp;
  131.  
  132.     _scanbit    += 1;
  133.     _scanbitcnt -= 1;
  134.   }
  135.  
  136.   /* copy changes to scanbitcnt and scanbit out to memory
  137.    */
  138.   scanbitcnt = _scanbitcnt;
  139.   scanbit    = _scanbit;
  140.  
  141.   /* use i_lim to encourage compilers to register loop limit
  142.    */
  143.   i_lim = wdth;
  144.   for (i=0; i<i_lim; i++)
  145.     buf[i] = scan_to_pix[(int) (buf[i] & 0xff)];
  146.  
  147.   while ((dotcnt > 0) && (dot->y == idx))
  148.   {
  149.     tmp = dot->x;
  150.  
  151.     if (dot->type == DotTypeStar)
  152.     {
  153.       if (buf[tmp] == PixTypeSpace)
  154.         buf[tmp] = PixTypeStar;
  155.     }
  156.     else
  157.     {
  158.       switch (buf[tmp])
  159.       {
  160.       case PixTypeLand:
  161.         buf[tmp] = PixTypeGridLand;
  162.         break;
  163.  
  164.       case PixTypeWater:
  165.         buf[tmp] = PixTypeGridWater;
  166.         break;
  167.       }
  168.     }
  169.  
  170.     dot    += 1;
  171.     dotcnt -= 1;
  172.   }
  173. }
  174.  
  175.  
  176. static void no_shade_row(scanbuf, rslt)
  177.      s8or32 *scanbuf;
  178.      u_char *rslt;
  179. {
  180.   int i, i_lim;
  181.  
  182.   /* use i_lim to encourage compilers to register loop limit
  183.    */
  184.   i_lim = wdth;
  185.   for (i=0; i<i_lim; i++)
  186.   {
  187.     switch (scanbuf[i])
  188.     {
  189.     case PixTypeSpace:        /* black */
  190.       rslt[0] = 0;
  191.       rslt[1] = 0;
  192.       rslt[2] = 0;
  193.       break;
  194.  
  195.     case PixTypeStar:         /* white */
  196.     case PixTypeGridLand:
  197.     case PixTypeGridWater:
  198.       rslt[0] = 255;
  199.       rslt[1] = 255;
  200.       rslt[2] = 255;
  201.       break;
  202.  
  203.     case PixTypeLand:         /* green */
  204.       rslt[0] = 0;
  205.       rslt[1] = 255;
  206.       rslt[2] = 0;
  207.       break;
  208.  
  209.     case PixTypeWater:        /* blue */
  210.       rslt[0] = 0;
  211.       rslt[1] = 0;
  212.       rslt[2] = 255;
  213.       break;
  214.  
  215.     default:
  216.       assert(0);
  217.     }
  218.  
  219.     rslt += 3;
  220.   }
  221. }
  222.  
  223.  
  224. static void compute_sun_vector(rslt)
  225.      double *rslt;
  226. {
  227.   rslt[0] = sin(sun_lon * (M_PI/180)) * cos(sun_lat * (M_PI/180));
  228.   rslt[1] = sin(sun_lat * (M_PI/180));
  229.   rslt[2] = cos(sun_lon * (M_PI/180)) * cos(sun_lat * (M_PI/180));
  230.  
  231.   XFORM_ROTATE(rslt, view_pos_info);
  232. }
  233.  
  234.  
  235. static void orth_compute_inv_x(inv_x)
  236.      double *inv_x;
  237. {
  238.   int i, i_lim;
  239.  
  240.   i_lim = wdth;
  241.   for (i=0; i<i_lim; i++)
  242.     inv_x[i] = INV_XPROJECT(i);
  243. }
  244.  
  245.  
  246. static void orth_shade_row(idx, scanbuf, sol, inv_x, rslt)
  247.      int     idx;
  248.      s8or32 *scanbuf;
  249.      double *sol;
  250.      double *inv_x;
  251.      u_char *rslt;
  252. {
  253.   int    i, i_lim;
  254.   int    val;
  255.   double x, y, z;
  256.   double scale;
  257.   double tmp;
  258.  
  259.   y = INV_YPROJECT(idx);
  260.  
  261.   /* save a little computation in the inner loop
  262.    */
  263.   tmp = 1 - (y*y);
  264.  
  265.   /* use i_lim to encourage compilers to register loop limit
  266.    */
  267.   i_lim = wdth;
  268.   for (i=0; i<i_lim; i++)
  269.   {
  270.     switch (scanbuf[i])
  271.     {
  272.     case PixTypeSpace:        /* black */
  273.       rslt[0] = 0;
  274.       rslt[1] = 0;
  275.       rslt[2] = 0;
  276.       break;
  277.  
  278.     case PixTypeStar:         /* white */
  279.     case PixTypeGridLand:
  280.     case PixTypeGridWater:
  281.       rslt[0] = 255;
  282.       rslt[1] = 255;
  283.       rslt[2] = 255;
  284.       break;
  285.  
  286.     case PixTypeLand:         /* green, blue */
  287.     case PixTypeWater:
  288.       x = inv_x[i];
  289.       z = tmp - (x*x);
  290.       z = SQRT(z);
  291.       scale = x*sol[0] + y*sol[1] + z*sol[2];
  292.       if (scale < 0)
  293.       {
  294.     val = night_val;
  295.       }
  296.       else
  297.       {
  298.     val = day_val_base + (scale * day_val_delta);
  299.     if (val > 255)
  300.       val = 255;
  301.     else
  302.       assert(val >= 0);
  303.       }
  304.  
  305.       if (scanbuf[i] == PixTypeLand)
  306.       {
  307.     /* land (green) */
  308.     rslt[0] = 0;
  309.     rslt[1] = val;
  310.     rslt[2] = 0;
  311.       }
  312.       else
  313.       {
  314.     /* water (blue) */
  315.     rslt[0] = 0;
  316.     rslt[1] = 0;
  317.     rslt[2] = val;
  318.       }
  319.       break;
  320.  
  321.     default:
  322.       assert(0);
  323.     }
  324.  
  325.     rslt += 3;
  326.   }
  327. }
  328.  
  329.  
  330. static void merc_shade_row(idx, scanbuf, sol, rslt)
  331.      int     idx;
  332.      s8or32 *scanbuf;
  333.      double *sol;
  334.      u_char *rslt;
  335. {
  336.   int    i, i_lim;
  337.   int    val;
  338.   double x, y, z;
  339.   double sin_theta;
  340.   double cos_theta;
  341.   double scale;
  342.   double tmp;
  343.  
  344.   y = INV_YPROJECT(idx);
  345.   y = INV_MERCATOR_Y(y);
  346.  
  347.   /* conceptually, on each iteration of the i loop, we want:
  348.    *
  349.    *   x = sin(INV_XPROJECT(i)) * sqrt(1 - (y*y));
  350.    *   z = cos(INV_XPROJECT(i)) * sqrt(1 - (y*y));
  351.    *
  352.    * computing this directly is rather expensive, however, so we only
  353.    * compute the first (i=0) pair of values directly; all other pairs
  354.    * (i>0) are obtained through successive rotations of the original
  355.    * pair (by inv_proj_scale radians).
  356.    */
  357.  
  358.   /* compute initial (x, z) values
  359.    */
  360.   tmp = sqrt(1 - (y*y));
  361.   x   = sin(INV_XPROJECT(0)) * tmp;
  362.   z   = cos(INV_XPROJECT(0)) * tmp;
  363.  
  364.   /* compute rotation coefficients used
  365.    * to find subsequent (x, z) values
  366.    */
  367.   tmp = inv_proj_scale;
  368.   sin_theta = sin(tmp);
  369.   cos_theta = cos(tmp);
  370.  
  371.   /* use i_lim to encourage compilers to register loop limit
  372.    */
  373.   i_lim = wdth;
  374.   for (i=0; i<i_lim; i++)
  375.   {
  376.     switch (scanbuf[i])
  377.     {
  378.     case PixTypeSpace:        /* black */
  379.       rslt[0] = 0;
  380.       rslt[1] = 0;
  381.       rslt[2] = 0;
  382.       break;
  383.  
  384.     case PixTypeStar:         /* white */
  385.     case PixTypeGridLand:
  386.     case PixTypeGridWater:
  387.       rslt[0] = 255;
  388.       rslt[1] = 255;
  389.       rslt[2] = 255;
  390.       break;
  391.  
  392.     case PixTypeLand:         /* green, blue */
  393.     case PixTypeWater:
  394.       scale = x*sol[0] + y*sol[1] + z*sol[2];
  395.       if (scale < 0)
  396.       {
  397.     val = night_val;
  398.       }
  399.       else
  400.       {
  401.     val = day_val_base + (scale * day_val_delta);
  402.     if (val > 255)
  403.       val = 255;
  404.     else
  405.       assert(val >= 0);
  406.       }
  407.  
  408.       if (scanbuf[i] == PixTypeLand)
  409.       {
  410.     /* land (green) */
  411.     rslt[0] = 0;
  412.     rslt[1] = val;
  413.     rslt[2] = 0;
  414.       }
  415.       else
  416.       {
  417.     /* water (blue) */
  418.     rslt[0] = 0;
  419.     rslt[1] = 0;
  420.     rslt[2] = val;
  421.       }
  422.       break;
  423.  
  424.     default:
  425.       assert(0);
  426.     }
  427.  
  428.     /* compute next (x, z) values via 2-d rotation
  429.      */
  430.     tmp = (cos_theta * z) - (sin_theta * x);
  431.     x   = (sin_theta * z) + (cos_theta * x);
  432.     z   = tmp;
  433.  
  434.     rslt += 3;
  435.   }
  436. }
  437.  
  438.  
  439. void render(rowfunc)
  440.      void (*rowfunc) _P((u_char *));
  441. {
  442.   int     i, i_lim;
  443.   s8or32 *scanbuf;
  444.   u_char *row;
  445.   double *inv_x;
  446.   double  sol[3];
  447.   double  tmp;
  448.  
  449.   scanbuf = (s8or32 *) malloc((unsigned) (sizeof(s8or32) * wdth));
  450.   row = (u_char *) malloc((unsigned) wdth*3);
  451.   assert((scanbuf != NULL) && (row != NULL));
  452.  
  453.   inv_x = NULL;
  454.   render_rows_setup();
  455.  
  456.   if (do_shade)
  457.   {
  458.     /* inv_x[] only gets used with orthographic projection
  459.      */
  460.     if (proj_type == ProjTypeOrthographic)
  461.     {
  462.       inv_x = (double *) malloc((unsigned) sizeof(double) * wdth);
  463.       assert(inv_x != NULL);
  464.       orth_compute_inv_x(inv_x);
  465.     }
  466.  
  467.     compute_sun_vector(sol);
  468.  
  469.     /* precompute shading parameters
  470.      */
  471.     night_val     = night * (255.99/100.0);
  472.     tmp           = terminator / 100.0;
  473.     day_val_base  = ((tmp * day) + ((1-tmp) * night))  * (255.99/100.0);
  474.     day_val_delta = (day * (255.99/100.0)) - day_val_base;
  475.   }
  476.  
  477.   /* main render loop
  478.    * (use i_lim to encourage compilers to register loop limit)
  479.    */
  480.   i_lim = hght;
  481.   for (i=0; i<i_lim; i++)
  482.   {
  483.     render_next_row(scanbuf, i);
  484.  
  485.     if (!do_shade)
  486.       no_shade_row(scanbuf, row);
  487.     else if (proj_type == ProjTypeOrthographic)
  488.       orth_shade_row(i, scanbuf, sol, inv_x, row);
  489.     else
  490.       merc_shade_row(i, scanbuf, sol, row);
  491.  
  492.     rowfunc(row);
  493.   }
  494.  
  495.   free(scanbuf);
  496.   free(row);
  497.  
  498.   if (inv_x != NULL) free(inv_x);
  499. }
  500.  
  501.  
  502. void do_dots()
  503. {
  504.   if (dots == NULL)
  505.     dots = extarr_alloc(sizeof(ScanDot));
  506.   else
  507.     dots->count = 0;
  508.  
  509.   if (do_stars) new_stars(star_freq);
  510.   if (do_grid) new_grid(grid_big, grid_small);
  511.  
  512.   qsort(dots->body, dots->count, sizeof(ScanDot), dot_comp);
  513. }
  514.  
  515.  
  516. static void new_stars(freq)
  517.      double freq;
  518. {
  519.   int      i;
  520.   int      x, y;
  521.   int      max_stars;
  522.   ScanDot *newdot;
  523.  
  524.   max_stars = wdth * hght * freq;
  525.  
  526.   for (i=0; i<max_stars; i++)
  527.   {
  528.     x = random() % wdth;
  529.     y = random() % hght;
  530.  
  531.     newdot = (ScanDot *) extarr_next(dots);
  532.     newdot->x    = x;
  533.     newdot->y    = y;
  534.     newdot->type = DotTypeStar;
  535.  
  536.     if ((big_stars) && (x+1 < wdth) && ((random() % 100) < big_stars))
  537.     {
  538.       newdot = (ScanDot *) extarr_next(dots);
  539.       newdot->x    = x+1;
  540.       newdot->y    = y;
  541.       newdot->type = DotTypeStar;
  542.     }
  543.   }
  544. }
  545.  
  546.  
  547. static void new_grid(big, small)
  548.      int big;
  549.      int small;
  550. {
  551.   int    i, j;
  552.   int    cnt;
  553.   double lat, lon;
  554.   double lat_scale, lon_scale;
  555.   double cs_lat[2];
  556.   double cs_lon[2];
  557.  
  558.   /* lines of longitude
  559.    */
  560.   lon_scale = M_PI / (2 * big);
  561.   lat_scale = M_PI / (2 * big * small);
  562.   for (i=(-2*big); i<(2*big); i++)
  563.   {
  564.     lon       = i * lon_scale;
  565.     cs_lon[0] = cos(lon);
  566.     cs_lon[1] = sin(lon);
  567.  
  568.     for (j=(-(big*small)+1); j<(big*small); j++)
  569.     {
  570.       lat       = j * lat_scale;
  571.       cs_lat[0] = cos(lat);
  572.       cs_lat[1] = sin(lat);
  573.  
  574.       new_grid_dot(cs_lat, cs_lon);
  575.     }
  576.   }
  577.  
  578.   /* lines of latitude
  579.    */
  580.   lat_scale = M_PI / (2 * big);
  581.   for (i=(1-big); i<big; i++)
  582.   {
  583.     lat       = i * lat_scale;
  584.     cs_lat[0] = cos(lat);
  585.     cs_lat[1] = sin(lat);
  586.     cnt       = 2 * ((int) ((cs_lat[0] * small) + 0.5)) * big;
  587.     lon_scale = M_PI / cnt;
  588.  
  589.     for (j=(-cnt); j<cnt; j++)
  590.     {
  591.       lon       = j * lon_scale;
  592.       cs_lon[0] = cos(lon);
  593.       cs_lon[1] = sin(lon);
  594.  
  595.       new_grid_dot(cs_lat, cs_lon);
  596.     }
  597.   }
  598. }
  599.  
  600.  
  601. static void new_grid_dot(cs_lat, cs_lon)
  602.      double *cs_lat;
  603.      double *cs_lon;
  604. {
  605.   int      x, y;
  606.   double   pos[3];
  607.   ScanDot *new;
  608.  
  609.   pos[0] = cs_lon[1] * cs_lat[0];
  610.   pos[1] = cs_lat[1];
  611.   pos[2] = cs_lon[0] * cs_lat[0];
  612.  
  613.   XFORM_ROTATE(pos, view_pos_info);
  614.  
  615.   if (proj_type == ProjTypeOrthographic)
  616.   {
  617.     /* if the grid dot isn't visible, return immediately
  618.      */
  619.     if (pos[2] <= 0) return;
  620.   }
  621.   else /* (proj_type == ProjTypeMercator) */
  622.   {
  623.     /* apply mercator projection
  624.      */
  625.     pos[0] = MERCATOR_X(pos[0], pos[2]);
  626.     pos[1] = MERCATOR_Y(pos[1]);
  627.   }
  628.  
  629.   x = XPROJECT(pos[0]);
  630.   y = YPROJECT(pos[1]);
  631.  
  632.   if ((x >= 0) && (x < wdth) && (y >= 0) && (y < hght))
  633.   {
  634.     new = (ScanDot *) extarr_next(dots);
  635.     new->x    = x;
  636.     new->y    = y;
  637.     new->type = DotTypeGrid;
  638.   }
  639. }
  640.